package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.TransactionHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.parent.interfaces.DynamicStrategy;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.dynamic.help.DynamicDetailsHelper;
import com.xbongbong.paas.service.log.crm.help.OperationLogHelp;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.parent.interfaces.logger.OperationLogHandle;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.contact.pojo.dto.ContactDeleteBatchDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactEditAttrUpdateDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactUpdateBatchDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactUpdateByBusinessRuleDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactUpdateDTO;
import com.xbongbong.pro.contact.pojo.vo.ContactDeleteBatchVO;
import com.xbongbong.pro.contact.pojo.vo.ContactUpdateBatchVO;
import com.xbongbong.pro.contact.pojo.vo.ContactUpdateByBusinessRuleVO;
import com.xbongbong.pro.contactuser.pojo.dto.ContactUserDeleteBatchDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerRestoreBatchDTO;
import com.xbongbong.pro.customercommunicate.pojo.dto.DynamicDTO;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicDeleteDTO;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicSaveDTO;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ContactDataRepeatDTO;
import com.xbongbong.pro.formdata.pojo.AfterSavePojo;
import com.xbongbong.pro.formdata.pojo.dto.SaasAnalysisDataDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteBatchOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.log.pojo.dto.UpdateBatchOperationLogDTO;
import com.xbongbong.pro.message.constant.ContactPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.team.TeamAfterVerifyDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.saas.analytical.impl.ContactValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContactUserEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.ShowFormatHelp;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.ContactUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.service.ContactService;
import com.xbongbong.saas.service.ContactUserService;
import com.xbongbong.saas.service.MarketActivityForStaticService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 联系人业务实现
 *
 * @author feng.zheng
 * @version v1.0
 * @date 2019/1/18 9:42
 * @since v1.0
 */
@Service("contactService")
public class ContactServiceImpl implements ContactService {

    private static final Logger LOG = LoggerFactory.getLogger(ContactServiceImpl.class);

    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ShowFormatHelp showFormatHelp;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ContactModel contactModel;
    @Resource
    private ContactUserModel contactUserModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private ContactUserService contactUserService;
    @Resource
    private CallCenterCommonService callCenterCommonService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private EsHelper esHelper;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private LabelModel labelModel;
    @Resource
    private ContactValidateAnalyticalServiceImpl contactAnalyticalService;
    @Resource
    private UserModel userModel;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private OperationLogFactory operationLogFactory;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private MarketActivityForStaticService marketActivityForStaticService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private DynamicStrategyFactory dynamicStrategyFactory;
    @Resource
    private DynamicDetailsHelper dynamicDetailsHelper;
    @Resource
    private TransactionHelp transactionHelp;

    /**
     * 联系人保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @author feng.zheng
     * @date 2019/1/18
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        contactAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 联系人保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     * @author feng.zheng
     */
    @Override
    public AfterSavePojo afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        AfterSavePojo afterSavePojo = new AfterSavePojo();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        Long contactId = newPaasFormDataEntity.getId();
        String corpid = newPaasFormDataEntity.getCorpid();
        Boolean isNew = saasFormSaveDTO.getIsNew();
        Long newCustomerId = FastJsonHelper.getLongFromFormData(newData, ContactEnum.CUSTOMER_NAME.getAttr());
        Long oldCustomerId = FastJsonHelper.getLongFromFormData(oldData, ContactEnum.CUSTOMER_NAME.getAttr());
        String creatorId = newPaasFormDataEntity.getCreatorId();
        UserEntity creatorUser = userModel.getByKey(creatorId, corpid);
        String creatorUserName = Objects.isNull(creatorUser) ? "" : creatorUser.getName();
        if (!isNew) {

            //保存直接走新的团队逻辑
            teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(),saasFormSaveDTO.getNewPaasFormDataEntity().getId(),newPaasFormDataEntity,saasFormSaveDTO.getIsImport(), false);

            if (!Objects.equals(newCustomerId, oldCustomerId)) {
                // 关联客户改变，删除原联系人协同团队
                //contactUserModel.deleteBatchByCustomerAndContact(oldCustomerId, contactId, corpid);
                // 建立联系人协同团队
                //userRelateCustomerContact(newCustomerId, contactId, corpid);

                // fix:21466 【成功部】联系人更换关联客户后主联系人显示异常
                if (Objects.equals(newData.get(ContactEnum.IS_MAIN.getAttr()), 1)) {
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termQuery(ContactEnum.getAttrConnectData(ContactEnum.IS_MAIN), 1));
                    boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.mustNot((termQuery(StringConstant.SAAS_LINK_BUSINESS_ID, contactId)));
                    boolQueryBuilder.filter(termQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), newCustomerId));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CONTACT.getType()));
                    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                    sourceBuilder.query(boolQueryBuilder);
                    SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CONTACT.getIndex());
                    searchRequest.source(sourceBuilder);
                    Long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
                    if (count !=null && count > 0L) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(ContactEnum.IS_MAIN.getAttr(), 0);
                        UpdateDataEntity updateData = ExplainUtil.getUpdateData(contactId, jsonObject, corpid);
                        contactModel.updateBatch(Collections.singletonList(updateData), corpid);
                    }
                }
            }
        } else {
            // 建立联系人协同团队
            afterSavePojo = teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(),saasFormSaveDTO.getNewPaasFormDataEntity().getId(),newPaasFormDataEntity,saasFormSaveDTO.getIsImport(), false);
            //userRelateCustomerContact(newCustomerId, contactId, corpid);

            if (!Objects.equals(saasFormSaveDTO.getIsImport(), 1)) {
                // 新建联系人消息推送
                PaasFormDataEntityExt customerEntity = customerModel.getByKey(newCustomerId, corpid);
                String customerName = "";
                if (Objects.nonNull(customerEntity)) {
                    customerName = customerEntity.getData().getString(CustomerManagementEnum.NAME.getAttr());
                }
                ContactEntityExt contactEntityExt = new ContactEntityExt();
                BeanUtil.copyProperties(newPaasFormDataEntity, contactEntityExt);
                String contactName = saasFormSaveDTO.getNewData().getString(ContactEnum.NAME.getAttr());
                List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CONTACT_NEW.getCode(), PushTypeEnum.CONTACT_NEW.getSubCode(), saasFormSaveDTO.getLoginUser(), contactEntityExt);
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), contactId, Collections.singletonList(contactId), SaasMarkEnum.SAAS.getCode(), saasFormSaveDTO.getBusinessType(), saasFormSaveDTO.getSubBusinessType());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(contactId), 0, null, I18nMessageUtil.getMessage(ContactPushConstant.CONTACT_NEW_TITLE), String.format(I18nMessageUtil.getMessage(ContactPushConstant.CONTACT_NEW_CONTENT),  creatorUser.getName(), customerName, contactName), null, options);
                baseProducer.sendMessage(PushTypeEnum.CONTACT_NEW, messageRabbitMqDTO);
         }

            if (!Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), saasFormSaveDTO.getDistributorMark())) {
                // 关联客户
                DynamicStrategy dynamicStrategy = dynamicStrategyFactory.getDynamicStrategy(ProjectLogEnum.CONTACT_CREATE.getSubType());
                transactionHelp.afterCommitOrCommitNow(p -> {
                    dynamicStrategy.save(DynamicSaveDTO.initDynamicSaveDTO(contactId, newPaasFormDataEntity.getFormId(), saasFormSaveDTO, creatorUser, null));
                });
            }
        }
        return  afterSavePojo;
        //TODO 一致性更新
        //TODO 日志
    }

    @Override
    public boolean contactRepeat(ContactDataRepeatDTO contactDataRepeatDTO) throws XbbException {
        return contactAnalyticalService.contactRepeat(contactDataRepeatDTO);
    }


    @Override
    public ContactUpdateBatchVO updateBatch(ContactUpdateBatchDTO contactUpdateBatchDTO) throws XbbException {
        ContactUpdateBatchVO contactUpdateBatchVO = new ContactUpdateBatchVO();
        try {
            String corpid = contactUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<ContactUpdateDTO> contactUpdateList = contactUpdateBatchDTO.getContactList();
            if (Objects.nonNull(contactUpdateList) && !contactUpdateList.isEmpty()) {
                contactUpdateList.forEach((item)->{
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
            }
            contactModel.updateBatch(updateList, corpid);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        }
        return contactUpdateBatchVO;
    }

    @Override
    public ContactUpdateBatchVO updateBatch(ContactUpdateBatchDTO contactUpdateBatchDTO, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        ContactUpdateBatchVO contactUpdateBatchVO = new ContactUpdateBatchVO();
        try {
            String corpid = contactUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<ContactUpdateDTO> contactUpdateList = contactUpdateBatchDTO.getContactList();
            if (Objects.nonNull(contactUpdateList) && !contactUpdateList.isEmpty()) {
                contactUpdateList.forEach((item)->{
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
            }
            contactModel.updateBatch(updateList, corpid);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        }
        return contactUpdateBatchVO;
    }

    @Override
    public ContactUpdateByBusinessRuleVO updateFormDataByBusinessRule(ContactUpdateByBusinessRuleDTO contactUpdateByBusinessRuleDTO) throws XbbException {
        ContactUpdateByBusinessRuleVO contactUpdateByBusinessRuleVO = new ContactUpdateByBusinessRuleVO();
        try {
            String corpid = contactUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = contactUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(contactUpdateByBusinessRuleDTO.getFormDataList(), corpid, contactUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                contactModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(contactUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("contactServiceImpl.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return contactUpdateByBusinessRuleVO;
    }

    /**
     * 根据联系人id队列查找符合要求的联系人列表
     *
     * @param corpid     公司id
     * @param contactIds 联系人id队列
     * @return List 联系人列表
     * @throws XbbException
     * @author youli.chen
     */
    @Override
    public List<ContactEntityExt> getContactListByIds(String corpid, List<Long> contactIds) throws XbbException {
        if (contactIds == null || contactIds.size() == 0) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(4);
        params.put("corpid", corpid);
        params.put("idIn", contactIds);
        params.put("start", 0);
        params.put("del", 0);
        params.put("pageNum", contactIds.size());
        return contactModel.findEntitys(params);
    }

    @Override
    public ContactDeleteBatchVO deleteBatch(ContactDeleteBatchDTO contactDeleteBatchDTO) throws XbbException {
        ContactDeleteBatchVO contactDeleteBatchVO = new ContactDeleteBatchVO();
        String corpid = contactDeleteBatchDTO.getCorpid();
        try {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(RedundantTemplateTypeEnum.CONTACT.getCode(), corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            Long formId = paasFormExplainEntity.getFormId();
            contactDeleteBatchDTO.setFormId(formId);
            String explains = paasFormExplainEntity.getExplains();
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
            // 查询所选客户列表
            List<Long> idIn = contactDeleteBatchDTO.getDataIdList();
            Map<String, Object> param = BeanUtil.convertBean2Map(contactDeleteBatchDTO, true);
            param.put("idIn", contactDeleteBatchDTO.getDataIdList());
            List<ContactEntityExt> contactList = contactModel.findEntitys(param);
            if (Objects.isNull(contactList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            //查询名称
            List<String> contactName= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(ContactEntityExt entityExt : contactList){
                JSONObject data = entityExt.getData();
                String name = FastJsonHelper.getStringOrDefaultFromFormData(data, ContactEnum.NAME.getAttr(), "");
                contactName.add(name);
            }
            // TODO 列表循环校验删除权限
            // 删除联系人
            if(!idIn.isEmpty()) {
                if(BasicConstant.ONE.equals(contactDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(idIn.size())){
                    contactModel.deleteByKey(idIn.get(0),corpid);
                }else {
                    contactModel.deleteBatch(idIn, corpid);
                }
                contactDeleteBatchVO.setDeleteIds(idIn);
            }
            // 删除联系人关系
            ContactUserDeleteBatchDTO contactUserDeleteBatchDTO = new ContactUserDeleteBatchDTO();
            BeanUtil.copyProperties(contactDeleteBatchDTO, contactUserDeleteBatchDTO);
            contactUserDeleteBatchDTO.setContactIdIn(idIn);
            contactUserService.deleteBatch(contactUserDeleteBatchDTO);

            Set<Long> customerIds = new HashSet<>();
            PaasFormDataEntityExt formData;
            for(ContactEntityExt entityExt : contactList){
                formData = saasUpdateHelp.getFormData(entityExt.getId(), contactDeleteBatchDTO.getCorpid(),XbbRefTypeEnum.CONTACT.getCode() );
                if (formData ==null ){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
                }
                JSONObject data = entityExt.getData();
                Long customerId = data.getLong(ContactEnum.CUSTOMER_NAME.getAttr());
                customerIds.add(customerId);
            }

            // 动态
            try {
                if(!Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),contactDeleteBatchDTO.getDistributorMark())) {
                    DynamicStrategy dynamicStrategy = dynamicStrategyFactory.getDynamicStrategy(ProjectLogEnum.CONTACT_DELETE.getSubType());
                    List<PaasFormDataEntityExt> allowDeletePaasFormDatas = new ArrayList<>(contactList.size());
                    BeanUtil.copyPropertiesList(contactList, allowDeletePaasFormDatas, PaasFormDataEntityExt.class);
                    FormDataDeleteBatchDTO formDataDeleteBatchDTO = BeanUtil.copyProperties(contactDeleteBatchDTO, FormDataDeleteBatchDTO.class, true);
                    dynamicStrategy.batchDelete(DynamicDeleteDTO.initDynamicDeleteDTO(formDataDeleteBatchDTO, idIn, allowDeletePaasFormDatas));
                }
            } catch (Exception e) {
                LOG.error("删除联系人动态失败：", e);
            }
            for(long customerId : customerIds){
                Map<String, String> sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                sortMap.put("field", ContactEnum.IS_MAIN.getAttr());
                sortMap.put("sort", SortOrder.DESC.toString());
                PaasFormDataEsListVO paasFormDataEsListVO = getEsListVoByLinkIdAndCondition(contactDeleteBatchDTO, customerId, ContactEnum.CUSTOMER_NAME.getAttr(), XbbRefTypeEnum.CONTACT.getCode(), new ArrayList<>(), sortMap, explainMap);
                List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
                // 判断删除联系人关联的客户是否只剩下一个联系人（bug:17151 客户只有1个联系人时，联系人默认为客户的主联系人）
                // List<ContactUserEntity> contactUserList = contactUserModel.getListByCustomerId(corpid, contactDeleteBatchDTO.getUserId(), customerId);
                if (paasFormDataESList.size() == 1) {
                    Long contactId = paasFormDataESList.get(0).getDataId();
                    ContactEntityExt contactEntityExt = contactModel.getByKey(contactId, corpid);
                    JSONObject contactEntityExtData = contactEntityExt.getData();
                    contactEntityExtData.put(ContactEnum.IS_MAIN.getAttr(), BasicConstant.ONE);
                    contactModel.update(contactEntityExt);
                }
            }
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, contactDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = contactDeleteBatchDTO.getUserId();
            String userName = contactDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(contactName, "、");

//            contactDeleteBatchDTO
            Integer singleFlag = contactDeleteBatchDTO.getSingleFlag();
            if(Objects.equals(0,singleFlag)||idIn.size() > 1){
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                DeleteBatchOperationLogDTO deleteBatchOperationLogDTO = new DeleteBatchOperationLogDTO( corpid,  userId,  userName, null,  operateTypeEnum,
                        null,  nameStr,  null,  idIn.size(),contactDeleteBatchDTO.getHttpHeader(),contactDeleteBatchDTO.getFormId(),contactDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTACT.getCode());
                operationLogHandle.deleteBatch(infoArrPojoList,deleteBatchOperationLogDTO);
            } else if (Objects.equals(1,singleFlag)&&CollectionsUtil.isNotEmpty(idIn)){
                DeleteOperationLogDTO deleteOperationLogDTO = new DeleteOperationLogDTO(corpid,userId,userName,null,operateTypeEnum,idIn.get(0).toString(),nameStr,null,contactDeleteBatchDTO.getHttpHeader(),contactDeleteBatchDTO.getFormId(),contactDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTACT.getCode());
                operationLogHandle.delete(deleteOperationLogDTO);
            }
        }catch (XbbException e){
            throw e;
        }catch (Exception e) {
            LOG.error("contactModelImpl.deleteBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return contactDeleteBatchVO;
    }

    /**
     * 根据关联id和条件获取数据
     *
     * @param contactDeleteBatchDTO 入参
     * @param linkId              关联id
     * @return 数据
     * @throws XbbException 异常
     */
    private PaasFormDataEsListVO getEsListVoByLinkIdAndCondition(ContactDeleteBatchDTO contactDeleteBatchDTO, Long linkId, String attr, Integer businessType, List<ConditionsEntityExt> conditions, Map<String, String> sortMap, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        PaasFormDataEsListVO paasFormDataEsListVO;
        FormDataListDTO formDataListDTO = new FormDataListDTO();
        BeanUtil.copyProperties(contactDeleteBatchDTO, formDataListDTO);
        formDataListDTO.setAppId(null);
        formDataListDTO.setFormId(null);
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(attr);
        conditionsEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
        conditionsEntityExt.setValue(Collections.singletonList(linkId));
        conditionsEntityExt.setFieldType(FieldTypeEnum.TEXT.getType());
        conditions.add(conditionsEntityExt);
        formDataListDTO.setDel(DelEnum.NORMAL.getDel());
        formDataListDTO.setConditions(conditions);
        formDataListDTO.setBusinessType(businessType);
        formDataListDTO.setSortMap(sortMap);
        formDataListDTO.setExplainMap(explainMap);
        formDataListDTO.setSearchSubForm(false);
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataListDTO.getCorpid(), formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark());
        paasFormDataEsListVO = paasFormDataEsModel.list(formDataListDTO, indexTypeEnum);
        return paasFormDataEsListVO;
    }

    @Override
    public ListAppVO formatContactAppList(FormDataListDTO formDataListDTO, List<PaasFormDataEntityExt> esEntities, Integer totalCount) throws XbbException{
        List<AppListPojo> appListPojos = new ArrayList<>();
        List<Long> customerIdIn = new ArrayList<>();
        String corpid = formDataListDTO.getCorpid();
        Long formId = formDataListDTO.getFormId();
        String userId = formDataListDTO.getUserId();
        Integer businessType = formDataListDTO.getBusinessType();
        customerIdIn.add(-1L);
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        for(PaasFormDataEntityExt entity : esEntities){
            JSONObject data = entity.getData();
            saasSaveHelp.formatLinkBusiness4Save(data, ContactEnum.CUSTOMER_NAME.getAttr(), ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), ContactEnum.CUSTOMER_NAME.getFieldType());
            Long customerId;
            try {
                customerId = FastJsonHelper.getLongOrDefaultFromFormData(data, ContactEnum.CUSTOMER_NAME.getAttr(), -1L);
            } catch (Exception e) {
                customerId = -1L;
            }
            customerIdIn.add(customerId);
        }

        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

        boolean isActiveCall = callCenterCommonService.isOpenCallDingTalk(corpid, userId);

        for (PaasFormDataEntityExt entity : esEntities) {
            JSONObject data = entity.getData();

            Long id = entity.getDataId();
            String name = FastJsonHelper.getStringOrDefaultFromFormData(data, ContactEnum.NAME.getAttr(), "");
            FieldAttrEntity contactNameExplain = null;
            //电话可见判断
            Integer contactAttrVisible = 0;
            for (FieldAttrEntity explain : explainList) {
                if (Objects.equals(explain.getAttr(), ContactEnum.NAME.getAttr()) && Objects.equals(explain.getIsOpen(), 1)) {
                    contactNameExplain = explain;
                }
                if (Objects.equals(explain.getAttr(), ContactEnum.PHONE.getAttr()) && Objects.equals(explain.getIsOpen(), 1)) {
                    contactAttrVisible = explain.getVisible();
                }
            }

            if (contactNameExplain != null && contactNameExplain.getVisible() == 0) {
                name = StringConstant.INVISIBLE_VALUE;
            }
            JSONObject superScript = new JSONObject();
            JSONObject others = new JSONObject();


            List<SummaryDataPoJo> summaryList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.SUMMARY_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<SummaryDataPoJo> lablesList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.LABELS_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<FormTitlePoJo> titleList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.TITLE_LIST, new JSONArray()).toJavaList(FormTitlePoJo.class);
            /*-- 其他 -*/
            // 话务中心用户可以看到拨号列表
            JSONArray contactPhoneArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, ContactEnum.PHONE.getAttr(), new JSONArray());
            commonHelp.setContactPhone(others, contactPhoneArray, isActiveCall, contactAttrVisible, entity, data);
            boolean showAliyunCall = saasListHelp.checkShowCall(userEntity, formDataListDTO.getExplainMap(), entity);
            Boolean activeAliyunCall = callCenterCommonService.isActiveAliyunCall(corpid, userId).IsActiveAliyunAndHasRole();
            if(activeAliyunCall&&showAliyunCall){
                superScript.put("activeAliyunCall", 1);
            }else{
                superScript.put("activeAliyunCall", 0);
            }
            // 联系人头像
            JSONArray avatarArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, ContactEnum.AVATAR.getAttr(), new JSONArray());
            String avatar = CollectionsUtil.isNotEmpty(avatarArray) ? avatarArray.getString(0) : "";
            others.put("avatar", avatar);
            AppListPojo appListPojo = new AppListPojo(id, titleList, summaryList, superScript, lablesList, others, entity.getAppId(), entity.getMenuId(), entity.getFormId());
            appListPojo.setBusinessType(businessType);
            appListPojo.setDataId(id);
            appListPojos.add(appListPojo);
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(totalCount);
        return  listAppVO;
    }

    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        FieldAttrEntity linkCustomerField = new FieldAttrEntity();
        for(FieldAttrEntity fieldAttrEntity :explainList) {
            if (Objects.equals(fieldAttrEntity.getAttr(), ContactEnum.CUSTOMER_NAME.getAttr())) {
                linkCustomerField = fieldAttrEntity;
            }
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
        switch (redundantTemplateTypeEnum) {
            case CUSTOMER:
                String customerName = FastJsonHelper.getStringOrDefaultFromFormData(linkFormData, CustomerManagementEnum.NAME.getAttr(), "");
                linkCustomerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, customerName));
                break;
            default:
                break;
        }
    }

    @Override
    public void batchEditAttr(ContactEditAttrUpdateDTO contactEditAttrUpdateDTO) throws XbbException {
        try {
            String userId = contactEditAttrUpdateDTO.getUserId();
            String corpid = contactEditAttrUpdateDTO.getCorpid();
            String loginUserName = contactEditAttrUpdateDTO.getLoginUserName();
            Integer isBatch = contactEditAttrUpdateDTO.getIsBatch();
            Long formId = contactEditAttrUpdateDTO.getFormId();
            Integer businessType = contactEditAttrUpdateDTO.getBusinessType();
            List<Long> idIn = contactEditAttrUpdateDTO.getDataIdList();
            Map<String, Object> param = BeanUtil.convertBean2Map(contactEditAttrUpdateDTO, true);
            param.put("idIn", idIn);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<ContactEntityExt> contactList = contactModel.findEntitys(param);
            if (Objects.isNull(contactList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            // 审批通过后是否允许编辑
            Map<Long, Boolean> editAfterFinishedMap = paasProcessTemplateModel.getEditAfterFinishedMap(contactEditAttrUpdateDTO.getCorpid(), contactEditAttrUpdateDTO.getAppId(), contactEditAttrUpdateDTO.getMenuId(), contactEditAttrUpdateDTO.getLoginUser());
            List<PaasFormDataEntityExt> dataList = new ArrayList<>();
            BeanUtil.copyPropertiesList(contactList,dataList,PaasFormDataEntityExt.class);
            // 审批后能否编辑
            paasProcessTemplateModel.checkEditAfterFinished(editAfterFinishedMap, dataList);
            //权限团队校验前置了
            List<Long> errorIdList = new ArrayList<>();
//            List<Long> errorIdList = userTeamHelp.batchTeamMembersCheckEditPermission(contactEditAttrUpdateDTO.getBusinessType(), contactEditAttrUpdateDTO.getSaasMark(),
//                    contactEditAttrUpdateDTO.getMenuId(), contactEditAttrUpdateDTO.getLoginUser(), contactEditAttrUpdateDTO.getDistributorMark(),
//                    contactEditAttrUpdateDTO.getDataIdList(), new HashMap<>());
            List<String> errorNameList = new ArrayList<>();
            for (ContactEntityExt contactEntityExt : contactList) {
                if (errorIdList.contains(contactEntityExt.getId())) {
                    errorNameList.add(contactEntityExt.getData().getString(ContactEnum.NAME.getAttr()));
                }
            }
            String nameStr = org.apache.commons.lang.StringUtils.join(errorNameList, "、");
            if (CollectionUtils.isNotEmpty(errorNameList)) {
                throw new XbbException(UserTeamErrorCodeEnum.API_ERROR_271038.getCode(), String.format(UserTeamErrorCodeEnum.API_ERROR_271038.getMsg(), nameStr));
            }
            List<ContactUpdateDTO> contactUpdateList = new ArrayList<>();
            idIn.forEach((item)->{
                ContactUpdateDTO contactUpdateDTO = new ContactUpdateDTO();
                contactUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(contactEditAttrUpdateDTO.getFieldEditedList());
                contactUpdateDTO.setData(data);
                contactUpdateList.add(contactUpdateDTO);
            });
            if (!contactUpdateList.isEmpty()) {
                ContactUpdateBatchDTO contactUpdateBatchDTO = new ContactUpdateBatchDTO();
                BeanUtil.copyProperties(contactEditAttrUpdateDTO, contactUpdateBatchDTO);
                contactUpdateBatchDTO.setContactList(contactUpdateList);
                updateBatch(contactUpdateBatchDTO);
            }
            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ContactEntityExt item : contactList) {
                dataIdList.add(item.getId());
                JSONObject data = item.getData();
                String serialNo = item.getSerialNo();
                String opObjectName = data.getString(ContactEnum.NAME.getAttr());
                StringBuilder sb = new StringBuilder();
                opObjectName = opObjectName == null ? serialNo : sb.append(serialNo).append("（").append(opObjectName).append("）").toString();
                updataItemList.add(opObjectName);
            }

            if(Objects.nonNull(isBatch)){
                List<ContactEntityExt> newContactList = contactModel.findEntitys(param);
                List<PaasFormDataEntity> newDataList = new ArrayList<>();
                List<PaasFormDataEntity> oldDataList = new ArrayList<>();
                BeanUtil.copyPropertiesList(contactList,oldDataList,PaasFormDataEntity.class);
                BeanUtil.copyPropertiesList(newContactList,newDataList,PaasFormDataEntity.class);
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(contactEditAttrUpdateDTO.getSaasMark(),contactEditAttrUpdateDTO.getBusinessType());
                UpdateBatchOperationLogDTO updateBatchOperationLogDTO = new UpdateBatchOperationLogDTO(corpid, userId, loginUserName, dataIdList.size(), contactEditAttrUpdateDTO.getHttpHeader(),
                        contactEditAttrUpdateDTO.getLogFieldEditedList(), newDataList, oldDataList, formId, businessType, isBatch);
                operationLogHandle.updateBatch(updateBatchOperationLogDTO);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("contactServiceImpl.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        formDataAddDTO.setSerialNo("");
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        for (FieldAttrEntityForImport fieldAttr : fieldAttrList) {
            String attr = fieldAttr.getAttr();
            Integer fieldType = fieldAttr.getFieldType();
            String attrName = fieldAttr.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttr, dataJson);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttr.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttr, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                    formDataAddDTO.setSerialNo(cellValue.toString());
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, fieldAttr, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttr, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    /**
     * user关联到客户对应的所有联系人上（用于客户新建联系人以及删除联系人）
     */
    @Override
    public void userRelateCustomerContact(Long customerId, Long contactId, String corpid) throws XbbException {
        if (customerId == null || contactId == null || corpid == null) {
            return;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("customerId", customerId);
        param.put("corpid", corpid);
        param.put("del", 0);
        List<CustomerUserEntity> customerUserList = customerUserModel.findEntitys(param);
        List<ContactUserEntity> contactUserEntityList = new ArrayList<>();
        for (CustomerUserEntity customerUser : customerUserList) {
            ContactUserEntity contactUser = new ContactUserEntity();
            contactUser.setCorpid(corpid);
            contactUser.setUserId(customerUser.getUserId());
            contactUser.setUserName(customerUser.getUserName());
            contactUser.setDataId(contactId);
            contactUser.setCustomerId(customerId);
            contactUser.setIsMain(customerUser.getIsMain());
            contactUser.setDel(customerUser.getDel());
            contactUserEntityList.add(contactUser);
        }
        try {
            if (CollectionsUtil.isNotEmpty(contactUserEntityList)) {
                contactUserModel.insertBatch(contactUserEntityList, false);
            }
        } catch (XbbException e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

    }

    @Override
    public void getFormatData(SaasAnalysisDataDTO saasAnalysisDataDTO, JSONObject result) throws XbbException {
        showFormatHelp.formatLinkBusiness4Show(result, ContactEnum.CUSTOMER_NAME.getAttr(), ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), ContactEnum.CUSTOMER_NAME.getFieldType());
    }

    @Override
    public void dataConsistencyUpdateCustomer(String corpid, Long customerId, String customerName) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), customerId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<ContactEntityExt> contactEntityExtList = contactModel.findEntitys(param);

            if (Objects.nonNull(contactEntityExtList) && !contactEntityExtList.isEmpty()) {
                List<ContactUpdateDTO> contactUpdateDTOList = new ArrayList<>();
                for (ContactEntityExt entityExt : contactEntityExtList) {
                    ContactUpdateDTO contactUpdateDTO = new ContactUpdateDTO();
                    contactUpdateDTO.setId(entityExt.getId());
                    JSONObject data = new JSONObject();
                    data.put(ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), customerName);
                    contactUpdateDTO.setData(data);
                    contactUpdateDTOList.add(contactUpdateDTO);
                }
                ContactUpdateBatchDTO contactUpdateBatchDTO = new ContactUpdateBatchDTO();
                contactUpdateBatchDTO.setCorpid(corpid);
                contactUpdateBatchDTO.setContactList(contactUpdateDTOList);
                updateBatch(contactUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("ContactServiceImpl.dataConsistencyUpdateCustomer 出错， corpid=" + corpid + " customerId=" + customerId + " customerName=" + customerName, e);
        }
    }

    @Override
    public void updateRollback(List<Long> idIn, String corpid) throws XbbException {
        if (Objects.isNull(idIn) || idIn.isEmpty()) {
            return;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", idIn);
        param.put(StringConstant.CORPID, corpid);
        List<ContactEntityExt> contactList = contactModel.findEntitysWithoutSub(param);
        if (Objects.nonNull(contactList)) {
            for (ContactEntityExt item : contactList) {
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                BeanUtil.copyProperties(item, paasFormDataEntity);
                proEsHelper.reductionEsInUpdate(paasFormDataEntity, item.getId(), corpid, IndexTypeEnum.IDX_SAAS_CONTACT);
            }
        }
    }

    @Override
    public void addBatchForImport(List<ValidateDataDTO> needAddList, CustomerEntityExt customerEntityExt, Map<String, UserEntity> userMap, FormDataAddDTO formDataAddDTO) throws XbbException {
        List<PaasFormDataEntity> contactList = new ArrayList<>();
        String corpid = formDataAddDTO.getCorpid();
        Long customerId = customerEntityExt.getId();
        List<ReturnUserAndDepartmentPojo> ownerIdList = Objects.nonNull(formDataAddDTO.getOwnerId()) ? formDataAddDTO.getOwnerId() : new ArrayList<>();
        List<ReturnUserAndDepartmentPojo> coUserIdList = Objects.nonNull(formDataAddDTO.getCoUserId()) ? formDataAddDTO.getCoUserId() : new ArrayList<>();
        PaasFormExplainEntity contactExplain = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.CONTACT.getCode(), formDataAddDTO.getCorpid());
        List<FieldAttrEntity> explainList = JSONArray.parseArray(contactExplain.getExplains(), FieldAttrEntity.class);
        String labelAttr = null;
        for (FieldAttrEntity item : explainList) {
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.LABEL.getType())) {
                labelAttr = item.getAttr();
                break;
            }
        }
        Map<String, Long> labelPojoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (StringUtil.isNotEmpty(labelAttr)) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("formId", contactExplain.getFormId());
            param.put("corpid", contactExplain.getCorpid());
            param.put("appId", contactExplain.getAppId());
            param.put("del", DelEnum.NORMAL.getDel());
            List<LabelEntity> entitys = labelModel.findEntitys(param);
            entitys.forEach(item->{
                labelPojoMap.put(item.getName(), item.getId());
            });
        }
        //用于做一个标识符，后面需要主数据跟子数据有一个对应的关系
        Map<String, TeamAfterVerifyDTO> virtualAndMainMap = new HashMap<>();
        int num = 0;
        for (ValidateDataDTO validateDataDTO : needAddList) {
            JSONObject data = validateDataDTO.getData();
            if (data.isEmpty()) {
                continue;
            }
            if (StringUtil.isNotEmpty(labelAttr)) {
                String string = data.getString(labelAttr);
                if ( Objects.nonNull(string) ) {
                    String[] split = string.split(",");
                    JSONArray jsonArray = new JSONArray();
                    for (String s : split) {
                        if (Objects.nonNull(labelPojoMap.get(s))){
                            jsonArray.add(labelPojoMap.get(s));
                        }
                    }
                    data.put(labelAttr, jsonArray);
                }
            }
            // 把关联客户id塞进去
            data.put(ContactEnum.CUSTOMER_NAME.getAttr(), customerId);
            String customerName = customerEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr());
            if (StringUtil.isNotEmpty(customerName)) {
                data.put(ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), customerName);
            }
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(validateDataDTO, paasFormDataEntity);
            if (Objects.nonNull(formDataAddDTO.getOwnerId()) && !formDataAddDTO.getOwnerId().isEmpty()) {
                paasFormDataEntity.setOwnerId(formDataAddDTO.getOwnerId().get(0).getId().toString());
            } else {
                String ownerId = formDataAddDTO.getUserId();
                paasFormDataEntity.setOwnerId(ownerId);
            }

            FormDataUtil.removeSystemData(data);
            paasFormDataEntity.setData(data);
            paasFormDataEntity.setSerialNo(validateDataDTO.getSerialNo());
            // 所属部门的id，由前端传入
            paasFormDataEntity.setDepartmentId(validateDataDTO.getDepartmentId());
            paasFormDataEntity.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
            paasFormDataEntity.setCreatorId(formDataAddDTO.getUserId());
            paasFormDataEntity.setAddTime(DateTimeUtil.getInt());
            paasFormDataEntity.setUpdateTime(DateTimeUtil.getInt());
            contactList.add(paasFormDataEntity);
            //后面我需要记录每一条主数据跟主数据团队的信息，又不想增加字段，所以用了以前的uuid字段
            num++;
            paasFormDataEntity.setUuid(String.valueOf(num));
            virtualAndMainMap.put(String.valueOf(num), validateDataDTO.getTeamAfterVerifyDTO());
        }
        if(CollectionsUtil.isEmpty(contactList)){
            return;
        }
        contactModel.insertBatch(contactList, true);
        Integer distributorMark = formDataAddDTO.getDistributorMark();
        if (Objects.equals(distributorMark, DistributorMarkEnum.DISTRIBUTOR.getCode())) {
            List<ContactUserEntity> contactUserList = new ArrayList<>();
            for (PaasFormDataEntity paasFormDataEntity : contactList) {
                Long contactId = paasFormDataEntity.getId();
                for (ReturnUserAndDepartmentPojo ownIdObject : ownerIdList) {
                    String userId = ownIdObject.getId().toString();
                    ContactUserEntity contactUser = new ContactUserEntity();
                    contactUser.setCorpid(corpid);
                    contactUser.setIsMain(BasicConstant.MAIN_USER);
                    contactUser.setUserId(userId);
                    contactUser.setUserName("");
                    if (userMap.containsKey(userId)) {
                        contactUser.setUserName(userMap.get(userId).getName());
                    }
                    contactUser.setDataId(contactId);
                    contactUser.setCustomerId(customerId);
                    contactUser.setDel(DelEnum.NORMAL.getDel());
                    contactUserList.add(contactUser);

                }
                for (ReturnUserAndDepartmentPojo coUserIdObject : coUserIdList) {
                    String userId = coUserIdObject.getId().toString();
                    ContactUserEntity contactUser = new ContactUserEntity();
                    contactUser.setCorpid(corpid);
                    contactUser.setIsMain(BasicConstant.COOP_USER);
                    contactUser.setUserId(userId);
                    contactUser.setUserName("");
                    if (userMap.containsKey(userId)) {
                        contactUser.setUserName(userMap.get(userId).getName());
                    }
                    contactUser.setDataId(contactId);
                    contactUser.setCustomerId(customerId);
                    contactUser.setDel(DelEnum.NORMAL.getDel());
                    contactUserList.add(contactUser);
                }
            }
            if (CollectionsUtil.isNotEmpty(contactUserList)) {
                contactUserModel.insertBatch(contactUserList, true);
            }
        }else {
            teamDataHelp.saveBatchBusUserTeam(contactList, virtualAndMainMap, BasicConstant.ONE, formDataAddDTO.getLoginUser());

            try {
                List<DynamicDTO> dynamicDTOS = new ArrayList<>(contactList.size());
                UserEntity creator = userModel.getByKeyIngoreDel(formDataAddDTO.getUserId(), corpid);
                PaasFormEntity paasForm = dynamicDetailsHelper.getPaasForm(corpid, contactExplain.getFormId(), XbbRefTypeEnum.CONTACT.getCode());
                for (PaasFormDataEntity paasFormDataEntity : contactList) {
                    DynamicDTO dynamicDTO = dynamicDetailsHelper.initDynamicDTO(formDataAddDTO.getUserId(), CrmLogMemoConstant.DYNAMIC_USER_IMPORT, ProjectLogEnum.CONTACT_CREATE.getSubType(),
                            DynamicDTO.initMemoHolder(creator.getName(), paasForm.getName()), null, null, paasFormDataEntity.getId());
                    dynamicDTO.setCustomerId(customerId);
                    dynamicDTO.setRefId(paasFormDataEntity.getId());
                    dynamicDTO.setRefBusinessType(XbbRefTypeEnum.CONTACT.getCode());
                    dynamicDTO.setRefName(paasFormDataEntity.getData().getString(ContactEnum.NAME.getAttr()));
                    dynamicDTOS.add(dynamicDTO);
                }
                dynamicDetailsHelper.insertDynamic(dynamicDTOS, corpid);
            } catch (Exception e) {
                LOG.error("导入联系人动态失败：", e);
            }
        }
    }

    /**
     * 数据还原
     * @param corpid
     * @param customerUpdateTimeMap
     * @param customerRestoreBatchDTO
     * @return
     * @throws
     * @author xingxing.xiao
     * @date 2019/09/18 09:24
     */
    @Override
    public void restoreBatch(String corpid, Map<Long, Long> customerUpdateTimeMap, CustomerRestoreBatchDTO customerRestoreBatchDTO) throws XbbException {
        try {
            // 根据客户的 id 和 updateTime 来查询要还原的数据
            List<Long> dataIdList = new ArrayList<>();
            List<String> contactNames = new ArrayList<>();
            BoolQueryBuilder booleanQuery = boolQuery();
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.DELETE.getDel()));
            for (Map.Entry<Long, Long> entry : customerUpdateTimeMap.entrySet()) {
                BoolQueryBuilder shouldQueryBuilder = boolQuery();
                shouldQueryBuilder.filter(termsQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), entry.getKey().toString()));
                shouldQueryBuilder.filter(rangeQuery(ContactEnum.UPDATE_TIME.getAttr()).gte(entry.getValue()));
                booleanQuery.should(shouldQueryBuilder);
            }
            booleanQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.SAAS_LINK_BUSINESS_ID);
            fieldList.add(ContactEnum.getAttrConnectData(ContactEnum.NAME));
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, booleanQuery, PaasFormDataEntityExt.class, fieldList);
            paasFormDataEntityExtList.forEach(item -> {
                dataIdList.add(item.getId());
                contactNames.add(item.getData().getString(ContactEnum.NAME.getAttr()));
            });
            if (dataIdList.isEmpty()) {
                return;
            }
            contactModel.restoreBatch(dataIdList, corpid, DelEnum.NORMAL.getDel());
            // 日志
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.REVERT_CANCEL;
            String nameStr = StringUtils.join(contactNames, "，");
            String userName = customerRestoreBatchDTO.getLoginUserName();
            String userId = customerRestoreBatchDTO.getUserId();
            if(dataIdList.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_REVERT_FORM_DATA), userName, operateTypeEnum.getName(), nameStr);
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.CONTACT.getName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CONTACT, operateTypeEnum,
                        "", "", memo, customerRestoreBatchDTO.getHttpHeader());
            } else if(Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_REVERT_FORM_DATA), userName, operateTypeEnum.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.CONTACT, operateTypeEnum,
                        dataIdList.get(0).toString(), nameStr, memo, customerRestoreBatchDTO.getHttpHeader());
            }
        } catch (Exception e){
            LOG.error("ContactServiceImpl.restoreBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        ContactUpdateBatchDTO contactUpdateBatchDTO = new ContactUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, contactUpdateBatchDTO);
        List<ContactUpdateDTO> contactList = new ArrayList<>();
        addBatchList.forEach(item->{
            ContactUpdateDTO contactUpdateDTO = new ContactUpdateDTO();
            contactUpdateDTO.setData(item.getData());
            contactUpdateDTO.setId(item.getId());
            contactList.add(contactUpdateDTO);
        });
        contactUpdateBatchDTO.setContactList(contactList);
        updateBatch(contactUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject newData = saasFormSaveDTO.getNewData();
        //Long contactId = newPaasFormDataEntity.getId();
        //String corpid = newPaasFormDataEntity.getCorpid();
        //Long newCustomerId = FastJsonHelper.getLongFromFormData(newData, ContactEnum.CUSTOMER_NAME.getAttr());
        // 建立联系人协同团队
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(),saasFormSaveDTO.getNewPaasFormDataEntity().getId(),newPaasFormDataEntity,saasFormSaveDTO.getIsImport(),true);
        //userRelateCustomerContact(newCustomerId, contactId, corpid);
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        Long contactId = newPaasFormDataEntity.getId();
        String corpid = newPaasFormDataEntity.getCorpid();
        Long newCustomerId = FastJsonHelper.getLongFromFormData(newData, ContactEnum.CUSTOMER_NAME.getAttr());
        Long oldCustomerId = FastJsonHelper.getLongFromFormData(oldData, ContactEnum.CUSTOMER_NAME.getAttr());

        //新逻辑的团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(),saasFormSaveDTO.getNewPaasFormDataEntity().getId(),newPaasFormDataEntity,saasFormSaveDTO.getIsImport(),true);

        if (!Objects.equals(newCustomerId, oldCustomerId)) {
            // 关联客户改变，删除原联系人协同团队
            //contactUserModel.deleteBatchByCustomerAndContact(oldCustomerId, contactId, corpid);
            // 建立联系人协同团队
            //userRelateCustomerContact(newCustomerId, contactId, corpid);
            // fix:21466 【成功部】
            if (Objects.equals(newData.get(ContactEnum.IS_MAIN.getAttr()), 1)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ContactEnum.getAttrConnectData(ContactEnum.IS_MAIN), 1));
                boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.mustNot((termQuery(StringConstant.SAAS_LINK_BUSINESS_ID, contactId)));
                boolQueryBuilder.filter(termQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), newCustomerId));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CONTACT.getType()));
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(boolQueryBuilder);
                SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CONTACT.getIndex());
                searchRequest.source(sourceBuilder);
                Long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
                if (count !=null && count > 0L) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(ContactEnum.IS_MAIN.getAttr(), 0);
                    UpdateDataEntity updateData = ExplainUtil.getUpdateData(contactId, jsonObject, corpid);
                    contactModel.updateBatch(Collections.singletonList(updateData), corpid);
                }
            }
        }
    }
}